/*!
 * \file jbossejb_analysis.c
 *
 * \brief jbossejb数据包解析
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 *
 * \version 2.0
 * \author wuwk
 * \date 2016/02/25
 *
 */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>

#include "frcomm.h"
#include "jbossejb_core.h"
#include "jbossejb_analysis.h"

#define EJB_FUNC                      "request.ejb.function"
#define EJB_FUNC_ARG                  "request.ejb.function.arg"

#define EJB_FUNC_RETURN               "response.ejb.function"

#define TYPE_BOOLEAN            "boolean"
#define TYPE_CHAR            "char"
#define TYPE_BYTE            "byte"
#define TYPE_SHORT            "short"
#define TYPE_INTEGER            "int"
#define TYPE_LONG            "long"
#define TYPE_FLOAT            "float"
#define TYPE_DOUBLE            "double"
#define TYPE_STRING          "java.lang.String"
#define TYPE_ARRAY            "["




/*!
 * username取得
 *
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return NULL:失败\n
 *         username
 *
 */
FR_STATIC char *__get_username(Frbyte_Packet *p_st_data)
{
    char *p_username = NULL;
    int i_idx = 0;
    int i_len = 0;

    if (p_st_data == NULL)
        return NULL;

    bytebuff_skip(p_st_data, 1); // 引号

    // 找第二个引号
    if (bytebuff_memstr(p_st_data, 0, 0, "\"", 1, &i_idx) == FR_FAIL)
        return NULL;

    i_len = i_idx - bytebuff_getPosition(p_st_data);
    p_username = (char *)frmalloc(i_len + 1);
    if (p_username == NULL)
        return NULL;

    if (bytebuff_get_bytes(p_st_data, p_username, i_len) == FR_FAIL)
    {
        frfree(p_username);
        return NULL;
    }
    p_username[i_len] = '\0';

    return p_username;
}

FR_STATIC int __skip_utf(Frbyte_Packet *p_st_data)
{
    uint16_t u16_len = 0;

    if (p_st_data == NULL || bytebuff_remaining(p_st_data) < 2)
        return FR_FAIL;

    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    if (u16_len != 0)
    {
        if (bytebuff_skip(p_st_data, u16_len) == FR_FAIL)
            return FR_FAIL;
    }

    return FR_SUCC;
}

FR_STATIC int __is_ascii(Frbyte_Packet *p_st_data)
{
    uint8_t u8_value = 0;

    if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
}

FR_STATIC int __get_bytes(Frbyte_Packet *p_st_data, int *p_i_bytes)
{
    uint8_t chr = 0;

    if (p_st_data == NULL || p_i_bytes == NULL)
        return FR_FAIL;

    if (bytebuff_peek_char(p_st_data, &chr) == FR_FAIL)
        return FR_FAIL;

    // ASCII
    if ((chr & 0x80) == 0)
    {
        *p_i_bytes = 1;
        return FR_SUCC;
    }

    if (chr >= 0x80)
    {
        if (chr >= 0xFC && chr <= 0xFD)
            *p_i_bytes = 6;
        else if (chr >= 0xF8)
            *p_i_bytes = 5;
        else if (chr >= 0xF0)
            *p_i_bytes = 4;
        else if (chr >= 0xE0)
            *p_i_bytes = 3;
        else if (chr >= 0xC0)
            *p_i_bytes = 2;
        else
            return FR_FAIL;
    }

    return FR_SUCC;
}

FR_STATIC int __get_arg_str(Frbyte_Packet *p_st_data, char **pp_arg)
{
    uint16_t u16_len = 0;
    char *p_arg = NULL;

    if (p_st_data == NULL || bytebuff_remaining(p_st_data) < 2)
        return FR_FAIL;

    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    if (u16_len != 0)
    {
        p_arg = (char *)frmalloc(u16_len + 1);
        if (p_arg == NULL)
            return FR_FAIL;

        if (bytebuff_get_bytes(p_st_data, p_arg, u16_len) == FR_FAIL)
        {
            frfree(p_arg);
            return FR_FAIL;
        }
        p_arg[u16_len] = '\0';

        *pp_arg = p_arg;
    }

    return FR_SUCC;
}

FR_STATIC int __get_string_by_len(Frbyte_Packet *p_st_data, int i_len, char **pp_data)
{
    char *p_data = NULL;
    int i_bytes = 0;
    int i_str_len = 0;
    int i_pos = 0;
    int i = 0;

    if (p_st_data == NULL || i_len == 0)
        return FR_FAIL;

    i_pos = bytebuff_getPosition(p_st_data);
    for (; i < i_len; i++)
    {
        if (__get_bytes(p_st_data, &i_bytes) == FR_FAIL)
            return FR_FAIL;

        i_str_len += i_bytes;
    }

    bytebuff_setPosition(p_st_data, i_pos);

    p_data = (char *)frmalloc(i_str_len + 1);
    if (p_data == NULL)
        return FR_FAIL;

    if (bytebuff_get_bytes(p_st_data, p_data, i_str_len) == FR_FAIL)
    {
        frfree(p_data);
        return FR_FAIL;
    }
    p_data[i_str_len] = '\0';

    *pp_data = p_data;

    return FR_SUCC;
}

FR_STATIC int __get_array_by_len(Frreport_body_data *p_st_body_data
                                   , Frbyte_Packet *p_st_data
                                   , int i_len
                                   , char *p_arg_str
                                   , char *p_key)
{
    char *p_data = NULL;
    int i_bytes = 0;
    int i_str_len = 0;
    int i_pos = 0;
    int i = 0;

    if (p_st_data == NULL || i_len == 0)
        return FR_FAIL;

    switch (*(p_arg_str+1))
    {
        case 'B': // byte数组
            p_data = (char *)frmalloc(i_len);
            if(p_data == NULL)
                return FR_FAIL;

            if(bytebuff_get_bytes(p_st_data, p_data, i_len) == FR_FAIL)
            {
                frfree(p_data);
                return FR_FAIL;
            }

            if (frreport_body_l7_add_bin(p_st_body_data, p_key, p_data, i_len) == FR_FAIL)
            {
                frfree(p_data);
                return FR_FAIL;
            }
            frfree(p_data);
            break;
        case 'C': // char数组
            if (jbossejb_arg_char_array(p_st_body_data, p_st_data, i_len, p_key) == FR_FAIL)
                return FR_FAIL;
            break;
        case 'S': // short数组
            if (jbossejb_arg_short_array(p_st_body_data, p_st_data, i_len, p_key) == FR_FAIL)
                return FR_FAIL;
            break;
        case 'I': // int数组
            if (jbossejb_arg_int_array(p_st_body_data, p_st_data, i_len, p_key) == FR_FAIL)
                return FR_FAIL;
            break;
        case 'J': // long数组
            if (jbossejb_arg_long_array(p_st_body_data, p_st_data, i_len, p_key) == FR_FAIL)
                return FR_FAIL;
        case 'F': // float数组
            if (jbossejb_arg_float_array(p_st_body_data, p_st_data, i_len, p_key) == FR_FAIL)
                return FR_FAIL;
        case 'D': // double数组
            if (jbossejb_arg_double_array(p_st_body_data, p_st_data, i_len, p_key) == FR_FAIL)
                return FR_FAIL;
        case 'Z': // boolean
            if (jbossejb_arg_boolean_array(p_st_body_data, p_st_data, i_len, p_key) == FR_FAIL)
                return FR_FAIL;
        default:
            break;
    }

    return FR_SUCC;
}

FR_STATIC int __get_func_arg_string(Frbyte_Packet *p_st_data
                                , Frreport_body_data *p_st_body_data
                                , char *p_key)
{
    char *p_data = NULL;
    uint8_t u8_value = 0;
    uint8_t u8_len = 0;
    uint16_t u16_len = 0;

    if (p_st_data == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
        return FR_FAIL;

    switch (u8_value)
    {
        case TYPE_STRING_EMPTY: //61
            if (frreport_body_l7_add_str(p_st_body_data, p_key, "") == FR_FAIL)
                return FR_FAIL;
            break;
        case TYPE_STRING_SMALL: //62
            if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
                return FR_FAIL;

            if (__get_string_by_len(p_st_data, u8_len, &p_data) == FR_FAIL)
                return FR_FAIL;

            if (frreport_body_l7_add_str(p_st_body_data, p_key, p_data) == FR_FAIL)
            {
                frfree(p_data);
                return FR_FAIL;
            }

            frfree(p_data);
            break;
        case TYPE_STRING_MEDIUM: //63
            if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;

            if (__get_string_by_len(p_st_data, u16_len, &p_data) == FR_FAIL)
                return FR_FAIL;

            if (frreport_body_l7_add_str(p_st_body_data, p_key, p_data) == FR_FAIL)
            {
                frfree(p_data);
                return FR_FAIL;
            }

            frfree(p_data);
        default:
            return FR_FAIL;
    }

    return FR_SUCC;
}

FR_STATIC int __get_func_arg_array(Frbyte_Packet *p_st_data
                                , Frreport_body_data *p_st_body_data
                                , char *p_arg_str
                                , char *p_key)
{
    uint8_t u8_value = 0;
    uint8_t u8_len = 0;
    uint16_t u16_len = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_arg_str == NULL)
        return FR_FAIL;

    if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
        return FR_FAIL;

    switch (u8_value)
    {
        case ID_ARRAY_EMPTY: // 41
            if (frreport_body_l7_add_str(p_st_body_data, p_key, "") == FR_FAIL)
                return FR_FAIL;
            break;
        case ID_ARRAY_SMALL: // 42
            if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
                return FR_FAIL;

            if (__get_array_by_len(p_st_body_data, p_st_data, u8_len, p_arg_str, p_key) == FR_FAIL)
                return FR_FAIL;
            break;
        case ID_ARRAY_MEDIUM:
            if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;

            if (__get_array_by_len(p_st_body_data, p_st_data, u16_len, p_arg_str, p_key) == FR_FAIL)
                return FR_FAIL;
            break;
        default:
            return FR_FAIL;
    }

    return FR_SUCC;
}

FR_STATIC int __get_func_arg_detail(char *p_arg_str
                                  , int i_len
                                  , Frbyte_Packet *p_st_data
                                  , Frreport_body_data *p_st_body_data
                                  , int i_count)
{
    char arr_key[64];
    char arr_char[3];
    char *p_utf8 = NULL;
    unsigned int ui_utf8_len = 0;
    uint8_t u8_value = 0;
    uint16_t u16_value = 0;
    uint32_t u32_value = 0;
    uint64_t u64_value = 0;
    union int32_float_bits u_32bits;
    union int64_double_bits u_64bits;
    float f_value = 0.0;
    double db_value = 0.0;
    int i_ret = 0;

    if (p_arg_str == NULL || i_len == 0)
        return FR_FAIL;

    snprintf(arr_key, sizeof(arr_key), "%s.%d", EJB_FUNC_ARG, i_count);

    if (strncmp(p_arg_str, TYPE_BOOLEAN, i_len) == 0)
    {
        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value == ID_BOOLEAN_TRUE) // 80:true
        {
            if (frreport_body_l7_add_int(p_st_body_data, arr_key, 1) == FR_FAIL)
                return FR_FAIL;
        }
        else if (u8_value == ID_BOOLEAN_FALSE) // 81:false
        {
            if (frreport_body_l7_add_int(p_st_body_data, arr_key, 0) == FR_FAIL)
                return FR_FAIL;
        }
        else
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_CHAR, i_len) == 0)
    {
        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value != ID_CHAR) // 77
            return FR_FAIL;

        memset(arr_char, 0x00, sizeof(arr_char));
        if (bytebuff_get_bytes(p_st_data, arr_char, 2) == FR_FAIL)
            return FR_FAIL;

        i_ret = iconv_to_utf8(arr_char, 2, (char *)"UNICODE", &p_utf8, &ui_utf8_len);
        if (i_ret == 2)
            return FR_FAIL;
        else if (i_ret == 1)
        {
            frfree(p_utf8);
            return FR_FAIL;
        }

        // char上报
        if (frreport_body_l7_add_str(p_st_body_data, arr_key, p_utf8) == FR_FAIL)
        {
            frfree(p_utf8);
            return FR_FAIL;
        }
        frfree(p_utf8);
    }
    else if (strncmp(p_arg_str, TYPE_BYTE, i_len) == 0)
    {
        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value != ID_BYTE) // 73
            return FR_FAIL;

        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        // byte上报
        if (frreport_body_l7_add_int(p_st_body_data, arr_key, u8_value) == FR_FAIL)
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_SHORT, i_len) == 0)
    {
        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value != ID_SHORT) // 74
            return FR_FAIL;

        if (bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;

        // short上报
        if (frreport_body_l7_add_int(p_st_body_data, arr_key, u16_value) == FR_FAIL)
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_INTEGER, i_len) == 0)
    {
         if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value != ID_INTEGER) // 75
            return FR_FAIL;

        if (bytebuff_get_int(p_st_data, 4, &u32_value, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;

        // int上报
        if (frreport_body_l7_add_int(p_st_body_data, arr_key, u32_value) == FR_FAIL)
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_LONG, i_len) == 0)
    {
        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value != ID_LONG) // 76
            return FR_FAIL;

        if (bytebuff_get_long(p_st_data, 8, &u64_value, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;

        // long上报
        if (frreport_body_l7_add_long(p_st_body_data, arr_key, u64_value) == FR_FAIL)
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_FLOAT, i_len) == 0)
    {
        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value != ID_FLOAT) // 78
            return FR_FAIL;

        if (bytebuff_get_int(p_st_data, 4, &u32_value, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;

        u_32bits.int_bits = u32_value;
        f_value = u_32bits.float_bits;

        // float上报
        if (frreport_body_l7_add_float(p_st_body_data, arr_key, f_value) == FR_FAIL)
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_DOUBLE, i_len) == 0)
    {
        if (bytebuff_get_char(p_st_data, &u8_value) == FR_FAIL)
            return FR_FAIL;

        if (u8_value != ID_DOUBLE) // 79
            return FR_FAIL;

        if (bytebuff_get_long(p_st_data, 8, &u64_value, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;

        u_64bits.int_bits = u64_value;
        db_value = u_64bits.double_bits;

        // double上报
        if (frreport_body_l7_add_double(p_st_body_data, arr_key, db_value) == FR_FAIL)
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_STRING, i_len) == 0)
    {
        // 解析string参数并上报
        if (__get_func_arg_string(p_st_data, p_st_body_data, arr_key) == FR_FAIL)
            return FR_FAIL;
    }
    else if (strncmp(p_arg_str, TYPE_ARRAY, 1) == 0)
    {
        // 解析array参数并上报
        if (__get_func_arg_array(p_st_data, p_st_body_data, p_arg_str, arr_key) == FR_FAIL)
            return FR_FAIL;
    }

    return FR_SUCC;
}

FR_STATIC int __get_func_arg(L7session_jbossejb_private *p_st_private
                  , Frbyte_Packet *p_st_data
                  , Frreport_body_data *p_st_body_data
                  , char *p_arg_str)
{
    char *p_comma = NULL;
    int i_arg_len = 0;
    int i_count = 0;

    if (p_st_private == NULL || p_st_data == NULL || p_st_body_data == NULL || p_arg_str == NULL)
        return FR_FAIL;

    while (1)
    {
        i_count++;

        p_comma = strchr(p_arg_str, ',');
        if (p_comma == NULL)
            i_arg_len = strlen(p_arg_str);
        else
            i_arg_len = p_comma - p_arg_str;

        // 取得参数值并上报
        if (__get_func_arg_detail(p_arg_str, i_arg_len, p_st_data, p_st_body_data, i_count) == FR_FAIL)
            return FR_FAIL;

        // 最后一个参数
        if (p_comma == NULL)
            break;
    }

}

/*!
 * jboss ejb请求函数解析
 *
 * \param *p_st_private        (L7session_jbossejb_private  jbossejb私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *i_need_report       (int      是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __jbossejb_message_data_cli2sev(L7session_jbossejb_private *p_st_private
                  , Frbyte_Packet *p_st_data
                  , Frreport_body_data *p_st_body_data
                  , int *i_need_report)
{
    L7Session_jbossejb *p_st_session = NULL;
    char *p_func_name = NULL;
    char *p_ejb_name = NULL;
    char *p_arg_str = NULL;
    uint8_t u8_flag = 0;
    uint8_t u8_len = 0;
    uint16_t u16_len = 0;
    int i_arg_num = 0;

    if (p_st_data == NULL || p_st_body_data == NULL  || p_st_private == NULL
        || p_st_private->p_st_session == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;
    if (bytebuff_get_char(p_st_data, &u8_flag) == FR_FAIL)
        return FR_FAIL;

    if (u8_flag != 3)
        return FR_FAIL;

    if (bytebuff_get_char(p_st_data, &u8_flag) == FR_FAIL)
        return FR_FAIL;

    if (u8_flag != 3)
        return FR_FAIL;

    // 取invocationId
    if (__get_invocation_id(p_st_private, p_st_data) == FR_FAIL)
        return FR_FAIL;

    // 函数名
    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    p_func_name = (char *)frmalloc(u16_len + 1);
    if (p_func_name == NULL)
        return FR_FAIL;

    if (bytebuff_get_bytes(p_st_data, p_func_name, u16_len) == FR_FAIL)
        goto err;

    p_func_name[u16_len] = '\0';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, EJB_FUNC, p_func_name) == FR_FAIL)
        goto err;
    frfree(p_func_name);
    p_func_name = NULL;

    // 参数
    if (__get_arg_str(p_st_data, &p_arg_str) == FR_FAIL)
        return FR_FAIL;

    // 02 + =>
    if (bytebuff_skip(p_st_data, 3) == FR_FAIL)
        goto err;

    // EJB名
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        goto err;

    p_ejb_name = (char *)frmalloc(u8_len + 1);
    if (p_ejb_name == NULL)
        goto err;

    if (bytebuff_get_bytes(p_st_data, p_ejb_name, u8_len) == FR_FAIL)
        goto err;

    p_ejb_name[u8_len] = '\0';

    // 设置title
    p_st_session->p_title = p_ejb_name;

    p_ejb_name = NULL;

    if (bytebuff_skip(p_st_data, 20) == FR_FAIL)
        return FR_FAIL;

    // ViewClass
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        return FR_FAIL;

    if (bytebuff_skip(p_st_data, u8_len) == FR_FAIL)
        return FR_FAIL;

    // 取函数参数并上报
    if (__get_func_arg(p_st_private, p_st_data, p_st_body_data, p_arg_str) == FR_FAIL)
        return FR_FAIL;



err:
    if (p_func_name)
        frfree(p_func_name);

    if (p_ejb_name)
        frfree(p_ejb_name);

    if (p_arg_str)
        frfree(p_arg_str);
}

/*!
 * jboss ejb请求解析
 *
 * \param *p_st_private        (L7session_jbossejb_private  jbossejb私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *i_need_report       (int      是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
int jbossejb_analysis_req(L7session_jbossejb_private *p_st_private
                  , Frbyte_Packet *p_st_data
                  , Frreport_body_data *p_st_body_data
                  , int *i_need_report)
{
    Protocol_info_jbossejb *p_st_protocol_info = NULL;
    L7Session_jbossejb *p_st_session = NULL;
    uint8_t u8_type = 0;
    uint8_t u8_flag = 0;
    char arr_server[64];
    int i_idx = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL  || p_st_private == NULL
        || p_st_private->p_st_session == NULL
        || p_st_private->p_st_fragment == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 5)
        return APM_L7_ANALYZE_TODO;

    p_st_session = p_st_private->p_st_session;

    bytebuff_skip(p_st_data, 4); // 长度

    if (bytebuff_get_char(p_st_data, &u8_type) == FR_FAIL)
        return FR_FAIL;

    switch (u8_type)
    {
        case '\x04':
            // username
            if (bytebuff_memstr(p_st_data, 0, 0, "username=", 9, &i_idx) == FR_FAIL)
                return FR_FAIL;

            bytebuff_setPosition(p_st_data, i_idx+9);

            p_st_session->p_username = __get_username(p_st_data);
            if (p_st_session->p_username == NULL)
                return FR_FAIL;

            return FR_SUCC;
        case '\x30': // message data
            if (bytebuff_get_char(p_st_data, &u8_flag) == FR_FAIL)
                return FR_FAIL;

            if ((u8_flag & 0x80) == 0)
                return FR_FAIL;

            bytebuff_skip(p_st_data, 5);
            if (__jbossejb_message_data_cli2sev(p_st_private, p_st_data, p_st_body_data, i_need_report) == FR_FAIL)
                return FR_FAIL;

            break;
        default:

    }

    return i_ret;
}

/*!
 * jbossejb响应解析
 *
 * \param *p_st_private        (L7session_jbossejb_private  jbossejb私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *i_need_report       (int      是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
int jbossejb_analysis_resp(L7session_jbossejb_private *p_st_private
                   , Frbyte_Packet *p_st_data
                   , Frreport_body_data *p_st_body_data
                   , int *i_need_report)
{
    Protocol_info_jbossejb *p_st_protocol_info = NULL;
    L7Session_jbossejb *p_st_session = NULL;
    uint8_t u8_type = 0;
    uinjbossejb2_t u32_respid = 0;
    uinjbossejb2_t u32_methodid = 0;
    uinjbossejb2_t u32_flag = 0;
    char arr_server[64];
    int i_idx = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL  || p_st_private == NULL
        || p_st_private->p_st_protocol_info == NULL
        || p_st_private->p_st_session == NULL
        || p_st_private->p_st_fragment == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 14)
        return FR_SUCC;

    p_st_protocol_info = p_st_private->p_st_protocol_info;
    p_st_session = p_st_private->p_st_session;

    bytebuff_skip(p_st_data, 4);
    i_ret = bytebuff_get_char(p_st_data, &u8_type);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 2);

    if (bytebuff_get_int(p_st_data, 4, &u32_respid, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    *i_need_report = jbossejb_NO;

    // session server
    if (p_st_protocol_info->p_version != NULL && p_st_session->p_server == NULL)
    {
        snprintf(arr_server, sizeof(arr_server), "weblogic-%s", p_st_protocol_info->p_version);
        p_st_session->p_server = frstrdup(arr_server);
        if (p_st_session->p_server == NULL)
            return FR_FAIL;
    }

    if (bytebuff_remaining(p_st_data) < 12)
        return FR_SUCC;

    // 头部结束
    bytebuff_skip(p_st_data, 8);

    // 区分是JMS或EJB
    if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, WEBLOGIC_EJB_BUSINESSOBJ, strlen(WEBLOGIC_EJB_BUSINESSOBJ), &i_idx) != FR_FAIL
         || p_st_private->is_ejb == 1)
    {
        p_st_private->is_ejb = 1;

        i_ret = jbossejb_ejb_analysis_resp(p_st_private, p_st_data, p_st_body_data, i_need_report);
        return i_ret;
    }

    if (bytebuff_get_int(p_st_data, 4, &u32_flag, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;
    if ((u32_flag & 0x1000) && p_st_private->i_browse_status == 1)
    {
        i_ret = __jbossejb_browsemsg_resp(p_st_private, p_st_data, p_st_body_data, i_need_report);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
        if (u32_respid != 0 && u32_respid == p_st_private->ui_responseid)
            return FR_SUCC;
        else
        {
            *i_need_report = jbossejb_NO;
            return FR_SUCC;
        }
    }
    else
    {
        if (bytebuff_remaining(p_st_data) < 14)
            return FR_SUCC;
        bytebuff_skip(p_st_data, 10);
        if (bytebuff_get_int(p_st_data, 4, &u32_methodid, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;
    }

    if (u32_respid != 0 && u32_respid == p_st_private->ui_responseid)
    {
        *i_need_report = jbossejb_YES;
        return FR_SUCC;
    }

    switch (u32_methodid)
    {
        case 15620:  // PushMessage(\x3d\x04)
            i_ret = __jbossejb_pushmsg_analysis(p_st_private, p_st_data, p_st_body_data);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            *i_need_report = jbossejb_YES;
            break;
        default:
            break;
    }

    if (i_ret == FR_SUCC && p_st_private->p_st_fragment->u32_left_len != 0)
    {
        bytebuff_set_skip(p_st_data, p_st_private->p_st_fragment->u32_left_len);
        return APM_L7_ANALYZE_TODO;
    }

    return i_ret;
}
